package org.trinity.netdisk.controller;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.trinity.netdisk.entity.User;
import org.trinity.netdisk.entity.UserFile;
import org.trinity.netdisk.enums.ResultCode;
import org.trinity.netdisk.exception.file.DeleteFailedException;
import org.trinity.netdisk.exception.file.DuplicateNameException;
import org.trinity.netdisk.exception.file.MoveUserFileException;
import org.trinity.netdisk.service.IFileService;
import org.trinity.netdisk.util.JWTUtil;
import org.trinity.netdisk.util.ResponseWrapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@SuppressWarnings("unused")
@RequestMapping("/file")
@RestController
public class FileController {
    @Autowired
    IFileService fileService;
    @Value("${storage}")
    private String path;

    @RequestMapping("/fileList")
    private Object fileList() {
        return path;
    }


    @RequestMapping("/getUserFileByDirId")
    private Object getUserFileByDirId(@RequestParam(required = false) Long dirId, HttpServletRequest request) {
        return new ResponseWrapper(ResultCode.SUCCESS, fileService.getFileByUserIdAndDirId(JWTUtil.getUserId(request), dirId));
    }

    @RequestMapping("/getUserFileFromRecycleBinByDirId")
    private Object getUserFileFromRecycleBinByDirId(Long dirId, HttpServletRequest request) {
        return new ResponseWrapper(ResultCode.SUCCESS, fileService.getFileFromRecycleBinByUserIdAndDirId(JWTUtil.getUserId(request), dirId));
    }

    @RequestMapping("/getAllFileType")
    private Object getAllFileType() {
        return new ResponseWrapper(ResultCode.SUCCESS, fileService.selectAllFileType());
    }

    @RequestMapping("/userUsage")
    private Object userUsage(HttpServletRequest request) {
        return new ResponseWrapper(ResultCode.SUCCESS, fileService.selectUserFileUsage(JWTUtil.getUserId(request)));
    }

    @RequestMapping("/createDir")
    private Object createDir(@RequestBody UserFile userFile, HttpServletRequest request) {
        try {
            userFile.setUserId(JWTUtil.getUserId(request));
            fileService.createDir(userFile);
            return new ResponseWrapper(ResultCode.SUCCESS);
        } catch (DuplicateNameException e) {
            return new ResponseWrapper(ResultCode.FILE_WITH_DUPLICATE_NAME);
        }
    }

    @RequestMapping("/delete/{fileId}")
    private Object delete(@PathVariable("fileId") Long fileId, HttpServletRequest request) {
        UserFile target = new UserFile();
        try {
            target.setId(fileId);
            target.setUserId(JWTUtil.getUserId(request));
            fileService.deleteFile(target);
            return new ResponseWrapper(ResultCode.SUCCESS);
        } catch (DeleteFailedException e) {
            e.printStackTrace();
            return new ResponseWrapper(ResultCode.SPECIFIED_QUESTIONED_USER_NOT_EXIST);
        }
    }

    @RequestMapping("/deleteFromRecycleBin/{fileId}")
    private Object deleteFromRecycleBin(@PathVariable("fileId") Long fileId, HttpServletRequest request) {
        UserFile target = new UserFile();
        try {
            target.setId(fileId);
            target.setUserId(JWTUtil.getUserId(request));
            fileService.deleteFileFromRecycleBin(target);
            return new ResponseWrapper(ResultCode.SUCCESS);
        } catch (DeleteFailedException e) {
            e.printStackTrace();
            return new ResponseWrapper(ResultCode.SPECIFIED_QUESTIONED_USER_NOT_EXIST);
        }
    }

    @RequestMapping("/recoverFromRecycleBin/{fileId}")
    private Object recoverFromRecycleBin(@PathVariable("fileId") Long fileId, HttpServletRequest request) {
        UserFile target = new UserFile();

        target.setId(fileId);
        target.setUserId(JWTUtil.getUserId(request));
        fileService.recoverFromRecycleBin(target);
        return new ResponseWrapper(ResultCode.SUCCESS);

    }

    @RequestMapping("/flashDetection")
    private Object flashDetection(String fileMd5, Long fileParentId, HttpServletRequest request, String fileName) {
        return fileService.flashDetection(JWTUtil.getUserId(request), fileMd5, fileParentId, fileName, request.getHeader("token"));
    }

    @RequestMapping("/uploadFile")
    private Object uploadFile(MultipartFile uploadedChunk, String fileMd5, Long fileSize, Integer chunkIndex, String chunkMd5, HttpServletRequest request, String fileName, @RequestParam(required = false) Long parentId) {
        return fileService.uploadFileChunk(JWTUtil.getUserId(request), uploadedChunk, fileName, fileMd5, fileSize, chunkIndex, chunkMd5, parentId, request.getHeader("token"));
    }

    @RequestMapping("/chunkHandler")
    private Object chunkHandler(String md5, Long size) {
        return new ResponseWrapper(ResultCode.SUCCESS, fileService.chunkHandler(md5, size));
    }

    @RequestMapping("/renameUserFile")
    private Object renameUserFile(@RequestBody UserFile userFile, HttpServletRequest request) {
        userFile.setUserId(JWTUtil.getUserId(request));
        try {
            fileService.renameUserFile(userFile);
            return new ResponseWrapper(ResultCode.SUCCESS);
        } catch (Exception e) {
            return new ResponseWrapper(ResultCode.RENAME_USER_FILE_FAILED);
        }
    }

    @RequestMapping("/moveUserFile")
    private Object moveUserFile(@RequestBody UserFile userFile, HttpServletRequest request) {
        userFile.setUserId(JWTUtil.getUserId(request));
        try {
            fileService.moveUserFile(userFile);
            return new ResponseWrapper(ResultCode.SUCCESS);
        } catch (MoveUserFileException e) {
            return new ResponseWrapper(ResultCode.TARGET_NOT_DIR);
        } catch (DuplicateNameException e) {
            return new ResponseWrapper(ResultCode.FILE_WITH_DUPLICATE_NAME);
        }
    }

    @RequestMapping("/download/{userFileId}/{token}")
    private void download(@PathVariable("userFileId") Long userFileId, @PathVariable("token") String token, HttpServletRequest request,
                          HttpServletResponse response, @RequestHeader HttpHeaders httpHeaders) throws IOException {
        fileService.download(userFileId, response
                , httpHeaders, token);
    }


    @RequestMapping("/preview/{userFileId}/{token}")
    private void filePreview(@PathVariable("userFileId") Long userFileId, @PathVariable("token") String token, HttpServletRequest request,
                             HttpServletResponse response, @RequestHeader HttpHeaders httpHeaders) throws IOException {
        //预览限速512k/s
        int previewBuffLimit = 524288;
        User user = JWTUtil.getUserVale(token);
        user.getRole().setDownloadLimit(previewBuffLimit);
        String limitToken = JWTUtil.sign(user);
        fileService.download(userFileId, response, httpHeaders, limitToken);
    }

    @RequestMapping("/search/{filename}")
    private Object search(@PathVariable("filename") String filename, HttpServletRequest request) {
        return new ResponseWrapper(ResultCode.SUCCESS, fileService.searchFile(JWTUtil.getUserId(request), filename));
    }

    @RequestMapping("/copy/{userFileId}/{to}")
    private Object copy(@PathVariable("userFileId")Long userFileId,@PathVariable("to") Long to, HttpServletRequest request){
        Long userId = JWTUtil.getUserId(request);
        fileService.copy(userFileId,userId,to);
        return new ResponseWrapper(ResultCode.SUCCESS);
    }
}
